# ============================================================
# * Copyright © hk. 2022-2025. All rights reserved.
# * File name: CMakeLists.txt
# * Author   : 苏木
# * Date     : 2025-05-22
# * Version  : 
# * Description: cmake version 3.16.3
# ============================================================
## https://cmake.com.cn/cmake/help/latest/guide/tutorial/index.html
## https://cmake.org/cmake/help/latest/

# 指定 CMake 的最低版本要求
# --------------------------------------------------
cmake_minimum_required(VERSION 3.10)


# 设置项目名称和使用的编程语言
# --------------------------------------------------
project(SPROJECT C)


# 指定可执行程序和源文件
# --------------------------------------------------
add_executable(app_demo.out main.c)


# 通用命令属性，set_property()和get_property()，可以在任何类型的实体上设置和获取任何属性。
# --------------------------------------------------

# 1. set_property(entitySpecific
#  			      [APPEND] [APPEND_STRING]
#  			      PROPERTY propName [value1 [value2 [...]]])
# entitySpecific 定义了设置属性的实体，它必须是以下属性之一:
#                   GLOBAL          表示构建本身，因此不需要特定的实体名称。
#                   DIRECTORY [dir] 如果没有名为dir的目录，则使用当前源目录。
#                   TARGET [target1 [target2 [...]]]
#                   SOURCE [source1 [source2 [...]]]
#                   INSTALL [file1 [file2 [...]]]
#                   TEST [test1 [test2 [...]]]
#                   CACHE [var1 [var2 [...]]]		
# PROPERTY       关键字将剩下的参数标记为定义属性名和值。
# propName       通常会匹配CMake文档中定义的一种属性，值是特定于属性的。
#                除了CMake已经定义的属性外，还允许项目创建新的属性。这些特定于项目的属性意味着什么，
#                以及如何影响构建，这将取决于项目。如果选择这样做，对于项目来说，明智的做法是在属性
#                名称上使用一些特定于项目的前缀，以避免与CMake或其他第三方包定义的属性发生名称冲突。
# APPEND、APPEND_STRING 控制已有值(的命名)属性的更新方式。如果这两个关键字都没有指定，则将值替换为之前的(任意)值。
#                       APPEND关键字可以将行为的附加属性值累加形成一个列表，
#                       而APPEND_STRING关键词需要现有价值和附加新的价值，这里可以连接两个字符串而不是作为一个列表
#                       	|之前值|  新值  |  无关键字 |  APPEND   | APPEND_STRING |
#                       	| foo |  bar  |    bar   | foo;bar   |    foobar     |
#                       	| a;b |  c;d  |    c;d   |  a;b;c;d  |    a;bc;d     |


# 2. get_property(resultVar entitySpecific
#                 PROPERTY propName
#                 [DEFINED | SET | BRIEF_DOCS | FULL_DOCS])
# PROPERTY       关键字是必需的，并且后面要跟检索属性的名称。检索的结果存储在一个变量中，该变量的名称由resultVar给出。
# entitySpecific 部分类似于set_property()
#                   GLOBAL          GLOBAL将构建作为整体来引用。
#                   DIRECTORY [dir] DIRECTORY可以与指定目录一起使用，也可以不指定特定目录，如果没有提供目录，则默认为当前源目录。大多数作用域，必须命名该作用域内的特定实例，并将检索附加到该实例的属性请求中。
#                   TARGET target
#                   SOURCE source
#                   INSTALL file
#                   TEST test
#                   CACHE var
#                   VARIABLE        VARIABLE略有不同，变量名指定为propName，而不是附加到VARIABLE关键字上。这有点不直观，可以考虑一下如果变量使用VARIABLE关键字命名为实体。在这种情况下，属性名没有任何内容需要指定，将VARIABLE看作指定作用范围可能会有所帮助。以这种方式理解变量时，其与其他类型变量的处理方式是一致的。
# DEFINED        检索的结果将是一个布尔值，确定命名的属性是否定义。在VARIABLE的作用域内查询，只有在指定的变量使用define_property()命令显式定义时(见下面)，结果才为真。
# SET            检索的结果将是一个布尔值，确定命名的属性是否已经设置。这是一个比DEFINED的更强的测试，测试命名的属性是否已经实际给定了一个值(值本身是不相关的)。
# BRIEF_DOCS     检索已命名属性的字符串描述。如果没有为该属性定义字符串描述，结果将是字符串NOTFOUND。
# FULL_DOCS      检索已命名属性的完整文档。如果没有为该属性定义字符串描述，结果将是字符串NOTFOUND。

message(STATUS "[USER:TOP]==> ${CMAKE_VERSION} 通用命令属性：修改目标文件名")

# 设置目标属性
set_property(TARGET app_demo.out
  	PROPERTY 
    OUTPUT_NAME "super_app"   # 修改输出文件名,原本输出的可执行文件是app_demo.out，修改后生成的可执行文件名为 super_app
)

# 获取目标属性
get_property(output_name 
  TARGET app_demo.out 
  PROPERTY OUTPUT_NAME
)
message(STATUS "[USER:TOP]Target Property: OUTPUT_NAME = ${output_name}")  # 输出 super_app
message("")
